package tjs.study.notes.dotest.jvm.classload;

import tjs.study.notes.dotest.TjsStudyNotesApplication;

import java.lang.reflect.Method;


/**
 * Created by Nicky.Tang on 2021/10/9 4:07 下午
 * 参考博客
 * java.lang.ClassLoader#ClassLoader(java.lang.Void, java.lang.ClassLoader)
 *
 * @link https://blog.csdn.net/briblue/article/details/54973413
 * @since 02.12.10
 */
public class DoTestOfMyClassLoad {


    public static void main(String[] args) throws Exception {
//        restartWithMyClassLoader(args);
        //todo 怎么让所有类都用自定义类加载
//        testInvokeOtherPackage();
        testMoreClassLoader();
    }

    public static void testMoreClassLoader() throws Exception {
        OtherPackagerClassLoader noParentsClassLoader = new OtherPackagerClassLoader(TjsStudyNotesApplication.work_space_pre + "/target/classes/");
        Class<?> userClassOther = Class.forName("tjs.study.notes.dotest.jvm.classload.DoTestOfMyClassLoad", true, noParentsClassLoader);
        Class<?> userClassApp = Class.forName("tjs.study.notes.dotest.jvm.classload.DoTestOfMyClassLoad", true, Thread.currentThread().getContextClassLoader());
        System.out.println(userClassOther == userClassApp);//false 调用main方法前，DoTestOfMyClassLoad实际上默认已由AppClassLoader加载过了
        Object a =  userClassOther.newInstance();
        Object b =  userClassApp.newInstance();
        try {
            DoTestOfMyClassLoad object = (DoTestOfMyClassLoad) userClassOther.getConstructor().newInstance();
        } catch (ClassCastException ex) {
            ex.printStackTrace();//Exception in thread "main" java.lang.ClassCastException: tjs.study.notes.dotest.jvm.classload.DoTestOfMyClassLoad cannot be cast to tjs.study.notes.dotest.jvm.classload.DoTestOfMyClassLoad
        }
    }

    public static void restartWithMyClassLoader(String[] args) throws Exception {
        if (Thread.currentThread().getName().equals("restartedMain")) {
            ClassLoader classLoader = new OtherPackagerClassLoader(TjsStudyNotesApplication.work_space_pre + "/target/classes/");
            Class<?> mainClass = Class.forName("tjs.study.notes.dotest.jvm.classload.DoTestOfMyClassLoad", false, classLoader);
            Method mainMethod = mainClass.getDeclaredMethod("main", String[].class);
            mainMethod.invoke(null, (Object) args);//直接传args，标识多个参数；而实际上只有一个，所以要转成Object
        }
        System.out.println("DoTestOfMyClassLoad的classLoader是：" + DoTestOfMyClassLoad.class.getClassLoader());
    }

    public static void testInvokeOtherPackage() throws Exception {
        OtherPackagerClassLoader otherPackagerClassLoader = new OtherPackagerClassLoader(TjsStudyNotesApplication.work_space + "/jvm/classload/otherClass/");
        Class<?> userClass = otherPackagerClassLoader.loadClass("tjs.study.notes.dotest.jvm.classload.otherClass.OtherUserService");
        Object object = userClass.getConstructor().newInstance();
        Method loginMethod = userClass.getDeclaredMethod("login");
        loginMethod.invoke(object);
    }

}
